package com.powernode.ssm.springAnalysis.a03;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

/**
 * 后处理器排序：
 * 哪个后处理器先add，哪个的优先级就更高，由order决定
 *
 */
public class TestBeanFactory2 {

    public static void main(String[] args) {
        /**
         * 创建bean工厂并且注册bean，但是此时@Configuration、@Bean等注解都没有生效
         * 因为这些注解都没有被处理
         */
        //创建实例工厂对象
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //创建定义bean的对象
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
                .genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        //往工厂里面注册bean
        beanFactory.registerBeanDefinition("config",beanDefinition);
        System.out.println("===创建工厂，注册bean===");
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        //给beanFactory添加一些常用的后处理器，注意区分beanFactory后处理器和bean后处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        System.out.println("\n===添加beanFactory常用的后处理器===");
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        System.out.println("\n===调用beanFactory后处理器，使@Configuration、@Bean注解生效===");
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().forEach(e->{
            e.postProcessBeanFactory(beanFactory);
        });
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        System.out.println("\n===获取bean1，调用getBean2方法获取bean2===");
//        System.out.println(beanFactory.getBean(Bean1.class).getBean2());//null，说明依赖注入没有生效

        System.out.println("\n===建立bean常用的后处理器和bean的联系，当bean被调用时，bean相关注解会生效===");
        /**
         *  当出现这种情况时：
         *         @Autowired
         *         @Resource(name = "bean4")
         *         private Inter bean3;
         *  哪个后处理器先add，哪个的优先级就更高
         *  AutowiredAnnotationBeanPostProcessor的order 为 Ordered.LOWEST_PRECEDENCE - 2
         *  CommonAnnotationBeanPostProcessor的order 为 Ordered.LOWEST_PRECEDENCE - 3
         *  order越小，排序越靠前，因此CommonAnnotationBeanPostProcessor靠前，即
         *  @Resource优先级更高
         */
        beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
                .sorted(beanFactory.getDependencyComparator())//为添加bean后处理器做排序，取决于order
                .forEach(
                beanPostProcessor -> {
                    System.out.println(beanPostProcessor);
                    beanFactory.addBeanPostProcessor(beanPostProcessor);
                });
        //beanFactory.preInstantiateSingletons();//调用该方法就直接创建好所有的单例bean
        //默认只有用到这些bean时才会去创建bean，即懒加载
        System.out.println("\n======================");
        System.out.println(beanFactory.getBean(Bean5.class).getInter());//不为null，说明依赖注入已经生效
        /*
            学到了什么:
            a. beanFactory 不会做的事
                   1. 不会主动调用 BeanFactory 后处理器
                   2. 不会主动添加 Bean 后处理器
                   3. 不会主动初始化单例
                   4. 不会解析beanFactory 还不会解析 ${ } 与 #{ }
            b. bean 后处理器会有排序的逻辑
         */

    }

    @Configuration
    static class Config {
        @Bean
        public Bean5 bean5() {
            return new Bean5();
        }

        @Bean
        public Bean6 bean6() {
            return new Bean6();
        }

        @Bean
        public Bean3 bean3() {
            return new Bean3();
        }

        @Bean
        public Bean4 bean4() {
            return new Bean4();
        }
    }

    interface Inter {

    }

    static class Bean3 implements Inter {

    }

    static class Bean4 implements Inter {

    }

    static class Bean5 {
        private static final Logger log = LoggerFactory.getLogger(Bean5.class);

        public Bean5() {
            log.debug("构造 Bean1()");
        }

        @Autowired
        private Bean6 bean2;

        public Bean6 getBean2() {
            return bean2;
        }

        //由于Inter有两个实现类，因此以变量名bean3去注入名为bean3的实现类对象
//        @Autowired
//        private Inter bean3;

        //@Resource优先级高，注入名为bean4的实现类对象
//        @Resource(name = "bean4")
//        private Inter bean3;

        @Autowired
        @Resource(name = "bean4")
        private Inter bean3;

        public Inter getInter() {
            return bean3;
        }
    }

    static class Bean6 {
        private static final Logger log = LoggerFactory.getLogger(Bean6.class);

        public Bean6() {
            log.debug("构造 Bean2()");
        }
    }

}
